﻿// Author: AustralTek 
// Creation date: 2012/05/09
// http://www.australtek.com
// Copyright: 2009 - 2012

/* 
Glossary:
*/

(function(){
    function _ParseAttributes(){  
        var paths=null; 
        var MYVARS=null; 
        var MyPerc=75;
        function _Parse(attributes,target,condition){
            try{
                if (condition){
                    if (typeof(condition)=='string'){
                        switch(condition.toUpperCase()){
                            case 'COMPARISON':
                                return _ParseComparison(attributes,target,MyPerc);
                                break;
                            case 'MATCH':                               
                            default:
                                return _ParseMatched(attributes,target);
                                break;
                        }
                    }else if (typeof(condition)=='number'){
                        return _ParseComparison(attributes,target,MyPerc=condition);
                    }
                }else return _ParseMatched(attributes,target);                
            }catch(Error){alert(Error);}
        }   
        function _ParseComparison(attributes,target,perc){
            try{                  
                if (perc==null)perc = MyPerc;
                if ((attributes)&&(target)){
                    var srcPaths = _GetAttributesPath(attributes);
                    var tgtPaths = _GetAttributesPath(target);
                    _JoinPaths(srcPaths,tgtPaths);
                    for(var i=0;i<srcPaths.length;i++){
                        if ((srcPaths[i].Perc)&&(srcPaths[i].Perc>=perc)){
                            //join
                            var sp = srcPaths[i];
                            var tp = tgtPaths[sp.Index];
                            eval('target'+tp.Path+' = attributes ' + sp.Path);
                        }
                    }
                }
            }catch(Error){alert(Error);}
        }  
        function _ParseMatched(attributes,target){            
            var retStruct=target;
            try{
                MYVARS=[];
                if ((attributes)&&(target)){
                    var ar= _GetArrayAttributesFromObject(attributes);
                    if (_Duplicates(ar)){
                        //Copy attributes using absolute path
                        _CopyAbsoluteAttributes(attributes,target);
                    }else{
                        //Copy attributes using relatives path
                        for (var i=0;i<ar.length;i++){                        
                            var targetPath = _GetAttribute(ar[i],target);
                            if (targetPath){
                                var origPath = _GetAttribute(ar[i],attributes);
                                eval('retStruct'+targetPath+' = attributes'+origPath);
                            }
                        }
                    }
                }
                target = retStruct;
            }catch(Error){ alert(Error); }
            return target;
        }
        function _GetArrayAttributesFromObject(attributes){
            try{
                if (attributes){
                    for (var attr in attributes){
                        var type = 'string';
                        if ((attributes[attr]!=null)&&((attributes[attr].nodeType==undefined)||(attributes[attr].nodeType==null)||(typeof(attributes[attr].nodeType)!='number'))) type = typeof(attributes[attr]);                    
                        switch(type){
                            case 'object':
                                if (attributes.length==undefined) MYVARS.push(attr);
                                _GetArrayAttributesFromObject(attributes[attr]);
                                break;
                            case 'string':
                            case 'number':
                            case 'function':
                                MYVARS.push(attr);
                                break;
                        }
                    }
                }
            }catch(Error){};
            return MYVARS;
        }        
        function _Duplicates(ar){
            var duplicates=false;
            try{
                if (ar){
                    var sortAr = ar.sort();
                    for (var i = 0; i < sortAr.length - 1; i++) {
                        if (sortAr[i] == sortAr[i+1]) {duplicates=true;break;}
                    }
                }
            }catch(Error){ alert(Error); }
            return duplicates;
        }
        function _CopyAbsoluteAttributes(attributes,target){
            try{
                if ((attributes)&&(target)){
                    for(var attr in attributes){
                        if (target[attr]!=undefined){                            
                            var type = 'string';
                            if ((target[attr]!=null)&&((target[attr].nodeType==undefined)||(target[attr].nodeType==null)||(typeof(target[attr].nodeType)!='number'))) type = typeof(target[attr]);                           
                            switch(type){
                                case 'object':
                                    _CopyAbsoluteAttributes(attributes[attr],target[attr]);
                                    break;
                                case 'function':
                                case 'number':
                                case 'string':
                                    target[attr] = attributes[attr];
                                    break;
                             }
                        }else{
                            //Create??
                            target[attr]= attributes[attr];
                        }
                    }
                }
            }catch(Error){alert(Error);}
        }
        function _GetAttribute(prop,source){
            try{
                var str='';
                if ((prop)&&(source)){
                    for(var attr in source){
                        if (attr.toUpperCase()==prop.toUpperCase()) return (str += '[\''+attr+'\']');
                        else{
                            var type = 'string';
                            if ((source[attr]!=null)&&((source[attr].nodeType==undefined)||(source[attr].nodeType==null)||(typeof(source[attr].nodeType)!='number'))) type = typeof(source[attr]);                    
                            switch(type){
                                case 'object':
                                    var name = _GetAttribute(prop,source[attr]);
                                    if (name!='') return str +='[\''+attr+'\']'+name;
                                    break;
                                case 'function':
                                case 'number':
                                case 'string':
                                    break;
                            }
                        }

                    }
                }
            }catch(Error){}
            return str;
        }
        function _GetAttributePath(prop,target){
            try{
                var ret = _GetAttribute(prop,target);
                if (ret=='') ret='[\''+prop+'\']';
                return ret;
            }catch(Error){};
            return null;
        }   
        function _GetAttributesPath(attributes){
            try{           
               paths=[];
               _GeneratePaths(attributes,null);
               return paths;
            }catch(Error){alert(Error);}
        }
        function _GeneratePaths(attributes,words,source){
            try{
                if ((words==null)||(words==undefined))words='';
                if ((source==null)||(source==undefined))source='';
                if (attributes){
                    for(var attr in attributes){
                        var type = 'string';
                        if ((attributes[attr]!=null)&&((attributes[attr].nodeType==undefined)||(attributes[attr].nodeType==null)||(typeof(attributes[attr].nodeType)!='number'))) type = typeof(attributes[attr]);                    
                        switch(type){
                            case 'object':
    //                            if ((source==null) ||(source==undefined)){
    //                                source = '';//'[\''+attr+'\']';
    //                                words = '';
    //                            }
                                //else source += '[\''+attr+'\']';
                                _GeneratePaths(attributes[attr],((words!='')?words+',':'')+attr ,source+'[\''+attr+'\']' );//+',[\''+attr+'\']'
                                //source=null;
                                break;
                            case 'function':
                            case 'number':
                            case 'string':
                                paths.push({Words:((words!='')?words+',':'')+attr ,Path:source+'[\''+attr+'\']',Perc:0,Index:null});//',[\''+attr+'\']'
                                break;
                        }

                    }
                }
            }catch(Error){alert(Error);}
        }
        function _JoinPaths(src,tgt){
            try{
                if ((src)&&(src.length)&&(tgt)&&(tgt.length)){
                    for (var iSrc =0;iSrc<src.length;iSrc++){
                        var ret = _Compare(src[iSrc],tgt);
                        if (_CheckBetterPerc(src,ret)){
                            src[iSrc].Index = ret.Index;
                            src[iSrc].Perc = ret.Perc     
                        }else{
                            src[iSrc].Index =null;
                            src[iSrc].Perc=0;
                        }
                    }
                }
            }catch(Error){alert(Error);}  
        }
        function _CheckBetterPerc(src,elem){
            try{
                if (src){
                    for (var i=0;i<src.length;i++){
                        if (src[i].Index == elem.Index){
                            if (elem.Perc > src[i].Perc)return true;
                            else return false;
                        }

                    }
                }
            }catch(Error){alert(Error);}
            return true;
        }
        function _Compare(src,arTgt){ 
            var ret ={
                 Index:null
                ,Perc :0
            };      
            try{
                var total = 0;
                var puValue=0;
                if ((src)&&(arTgt)){
                    total = src.Path.length;
                    for (var itgt = 0;itgt<arTgt.length;itgt++){
                        var tgt = arTgt[itgt];
                        if ((tgt.Available==undefined) || (tgt.Available==true)){
                            if (src.Path==tgt.Path){
                                ret.Index=itgt;
                                ret.Perc=100;
                                tgt.Available = false;
                                return ret;
                            }
                            var srcW = src.Words.split(',');
                            var tgtW = tgt.Words.split(',');
                            var srcM =0;
                            var tgtM =0;
                            var value=0;
                            var uValue = 0;
                            var totW = (srcW.length>tgtW.length)?srcW.length:tgtW.length;
                            //Not compare better path yet, see _CompareWords
                            for (var i=0;i<srcW.length;i++){
                                var sW = srcW[i];
                                for (var k=tgtM;k<tgtW.length;k++){
                                    var _const = (i+k+1);
                                    var tW = tgtW[k];
                                    if (sW==tW){
                                        tgtM++;
                                        srcM++;
                                        //var t =  (srcW.length>tgtW.length)?srcW.length:tgtW.length; 
                                        //var m = (srcW.length<=tgtW.length)?srcW.length:tgtW.length;
                                        value += (100/totW);
                                        uValue += (100/totW)*_const;
                                        //next word
                                        break;
                                    }else{
                                        //compare each char
                                        var wPerc=0;
                                        var t = (sW.length>tW.length)?sW.length:tW.length; 
                                        var m = (sW.length<tW.length)?sW.length:tW.length;
                                        var ePerc = (100/t);
                                        var isch=0;
                                        var itch=0;
                                        if ((sW.indexOf(tW)!=-1)||(tW.indexOf(sW)!=-1)) wPerc =m*ePerc;
                                        else wPerc = _CompareWords(sW,tW);
                                        if (wPerc>45) {
                                            value += (wPerc/totW);
                                            uValue +=  (wPerc/totW)*_const;
                                        }
                                    }
                                }
                            }                         
                            if ((uValue>(puValue))||((value-ret.Perc)>5)){
                                ret.Perc = value;
                                ret.Index = itgt;
                                puValue = uValue;
                                if (value>75)tgt.Available = false;
                            }
                        }
                    }                               
                }
            }catch(Error){alert(Error);}
            return ret;
        }
        function _CompareWords(word1,word2){
            try{
                var w1 = (word1.length>word2.length)?word1:word2;
                var w2 = (word1.length<=word2.length)?word1:word2;
                var iw1=0;
                var iw2=0;
                var t = w1.length; 
                var m = w2.length;
                var ePerc = (100/t);
                var tPerc=0;
                var fPos=-1;
                var tPos=-1;
                var pPos=-1;
                var pw1=-1;
                var EOW=false;
                var indPerc=0;
                //try to get n char consecutive
                while (!EOW){
                    if(iw1==pw1) EOW = true;
                    for (var i =iw1;i<w1.length;i++){  
                        if (iw2==w2.length-1){
                            //end find 
                            tPos = fPos;
                            fPos =-1; 
                            iw2=0;
                            if (indPerc>tPerc) tPerc = indPerc;
                            indPerc = 0;
                            break;
                        }
                        for (var j=iw2;j<w2.length;j++){
                            if (w1[i] == w2[j]){
                                //next char
                                if (fPos==-1) fPos = i+1;
                                iw2 = j;
                                indPerc+=ePerc;
                                break;
                            }
                        }
                        //end w2
                    } 
                    pw1 = iw1;
                    iw1 = tPos;  
                } 
                return tPerc;
            }catch(Error){}
        }
        //Public Method
        this.Parse = _Parse;
    }
    window.ParseAttributes = new _ParseAttributes();
})();